#include "BspHelper.h"
#include <rtthread.h>

#include <stdbool.h>

#define BSP_XTAL32_PORT (GPIO_PORT_C)
#define BSP_XTAL32_IN_PIN (GPIO_PIN_15)
#define BSP_XTAL32_OUT_PIN (GPIO_PIN_14)

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/
// 初始化缓冲区

/** \brief 初始化外部缓冲区指南
 * 内部缓冲区无需初始化外部sdram。
 */
//uint8_t** test_buf_list;
//test_buf_list = malloc(4*sizeof(uint8_t*));
//test_buf_list[0] = (uint8_t*)(malloc(1536));
//strcpy((char*)test_buf_list[0], "test buf!\n");
// 结束初始化外部缓冲区样例

void Init_Usart_Buf(char *buf_name, size_t buf_list_size, size_t buf_size) {
}

/* Configures SWDT. */
static void App_SWDTCfg(void);

// 板子初始化。不要随意调整初始化顺序，可能会出错
void Bsp_Init(void) {
  /* Register write unprotected for some required peripherals. */
  LL_PERIPH_WE(LL_PERIPH_ALL);
	
	/** \brief 开始校准内部时钟
	*
	*/
	//CLK_LrcTrim(10);
	//CLK_HrcTrim(5);
	/* 开始校准内部时钟 */
	
  //Clock Config
  App_ClkCfg();
  
   if (BSP_XTAL32_Init() != LL_OK) {
	  for (;;) {;}
  }
  
  (void) SysTick_Init(1000U);

  //Port Config
  App_PortCfg();

  //Int Config
  App_IntCfg();
	
  // sdram
  App_SdramCfg();

  //SWDT Config
  App_SWDTCfg();

  //Timer0 Config
  App_Timer0Cfg();
  SWDT_FeedDog();

  //Timer2 Config
  App_Timer2Cfg();
  SWDT_FeedDog();
  
  //I2Cx Config
  //App_I2CxCfg();
  SWDT_FeedDog();

  //USARTx Config
  App_USARTxCfg();
  SWDT_FeedDog();

  //Dma Config
  App_DmaCfg();
  SWDT_FeedDog();

  //RTC Config
  App_RTCCfg();
  SWDT_FeedDog();
  /* Register write protected for some required peripherals. */
  LL_PERIPH_WP(LL_PERIPH_ALL);
}// Bsp_Init

//SWDT Config
static void App_SWDTCfg(void) {
  stc_swdt_init_t stcSwdtInit;

  /* SWDT configuration */
  stcSwdtInit.u32CountPeriod = SWDT_CNT_PERIOD256;
  stcSwdtInit.u32ClockDiv = SWDT_CLK_DIV32;
  stcSwdtInit.u32RefreshRange = SWDT_RANGE_0TO100PCT;
  stcSwdtInit.u32LPMCount = SWDT_LPM_CNT_STOP;
  stcSwdtInit.u32ExceptionType = SWDT_EXP_TYPE_RST;
  (void) SWDT_Init(&stcSwdtInit);

  /* First reload counter to start SWDT */
  SWDT_FeedDog();
}

int32_t BSP_XTAL32_Init(void) {
  stc_clock_xtal32_init_t stcXtal32Init;
  stc_fcm_init_t stcFcmInit;
  uint32_t u32TimeOut = 0UL;
  uint32_t u32Time = HCLK_VALUE / 5UL;

  if (CLK_XTAL32_ON == READ_REG8(CM_CMU->XTAL32CR)) {
    /* Disable xtal32 */
    (void) CLK_Xtal32Cmd(DISABLE);
    /* Wait 5 * xtal32 cycle */
    DDL_DelayUS(160U);
  }

  /* Xtal32 config */
  (void) CLK_Xtal32StructInit(&stcXtal32Init);
  stcXtal32Init.u8State = CLK_XTAL32_ON;
  stcXtal32Init.u8Drv = CLK_XTAL32_DRV_MID;
  stcXtal32Init.u8Filter = CLK_XTAL32_FILTER_ALL_MD;
  GPIO_AnalogCmd(BSP_XTAL32_PORT, BSP_XTAL32_IN_PIN | BSP_XTAL32_OUT_PIN, ENABLE);
  (void) CLK_Xtal32Init(&stcXtal32Init);

  /* FCM config */
  FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_FCM, ENABLE);
  (void) FCM_StructInit(&stcFcmInit);
  stcFcmInit.u32RefClock = FCM_REF_CLK_MRC;
  stcFcmInit.u32RefClockDiv = FCM_REF_CLK_DIV8192;
  stcFcmInit.u32RefClockEdge = FCM_REF_CLK_RISING;
  stcFcmInit.u32TargetClock = FCM_TARGET_CLK_XTAL32;
  stcFcmInit.u32TargetClockDiv = FCM_TARGET_CLK_DIV1;
  stcFcmInit.u16LowerLimit = (uint16_t) ((XTAL32_VALUE / (MRC_VALUE / 8192U)) * 96UL / 100UL);
  stcFcmInit.u16UpperLimit = (uint16_t) ((XTAL32_VALUE / (MRC_VALUE / 8192U)) * 104UL / 100UL);
  (void) FCM_Init(&stcFcmInit);
  /* Enable FCM, to ensure xtal32 stable */
  FCM_Cmd(ENABLE);
  for (;;) {
    if (SET == FCM_GetStatus(FCM_FLAG_END)) {
      FCM_ClearStatus(FCM_FLAG_END);
      if ((SET == FCM_GetStatus(FCM_FLAG_ERR)) || (SET == FCM_GetStatus(FCM_FLAG_OVF))) {
        FCM_ClearStatus(FCM_FLAG_ERR | FCM_FLAG_OVF);
      } else {
        (void) FCM_DeInit();
        FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_FCM, DISABLE);
		// 这里必须延迟，目的是等候晶振输入完全稳定，因此有源晶振也必须等候。
		DDL_DelayMS(1);
        return LL_OK;
      }
    }
    u32TimeOut++;
    if (u32TimeOut > u32Time) {
      (void) FCM_DeInit();
      FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_FCM, DISABLE);
      return LL_ERR_TIMEOUT;
    }
  }
}
